// Aaron curtis, incorporating code from 
// www.hacktronics.com LCD thermostat project

#include <OneWire.h>
#include <LiquidCrystal.h>
#include <ByteBuffer.h>

// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
int compressor = 5;
int heater = 4;
int plus_or_minus = 2;
int target_temp = 62;
int upper_temp, lower_temp;
int knob_raw = 0;
int relCycCnt = 1;
boolean heatOn;
boolean compOn;

ByteBuffer buffer;

OneWire  ds(2);        // ds18b20 pin #2 (middle pin) to Arduino pin 2

byte i;
byte present = 0;
byte data[12];
byte addr[8];
  
int HighByte, LowByte, SignBit, Whole, Fract, TReading, Tc_100, FWhole;

void setup(void) {
  
  // Initialize the buffer with a capacity for 256 bytes
  buffer.init(256);
  
  pinMode(compressor, OUTPUT);
  pinMode(heater, OUTPUT);
  Serial.begin(9600);
  lcd.begin(16,2);              // rows, columns.  use 2,16 for a 2x16 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0
  
    if ( !ds.search(addr)) {
      lcd.clear(); lcd.print("No more addrs");
      delay(1000);
      ds.reset_search();
      return;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      lcd.clear(); lcd.print("CRC not valid!");
      delay(1000);
      return;
  }
}

void getTemp() {
  int foo, bar;
  
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);

  for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
  
  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  
  if (SignBit) {
    TReading = -TReading;
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25
  Whole = Tc_100 / 100;          // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
  if (Fract > 49) {
    if (SignBit) {
      --Whole;
    } else {
      ++Whole;
    }
  }

  if (SignBit) {
    bar = -1;
  } else {
    bar = 1;
  }
  foo = ((Whole * bar) * 18);      // celsius to fahrenheit conversion section
  FWhole = (((Whole * bar) * 18) / 10) + 32;
  if ((foo % 10) > 4) {            // round up if needed
       ++FWhole;
  }
}

void doRelays(void) {
    if (FWhole>upper_temp) {
      digitalWrite(compressor, HIGH);
    }
    if (FWhole<target_temp) {
      digitalWrite(compressor, LOW);
    }
    if (FWhole>target_temp) {
      digitalWrite(heater, LOW);
    }
    if (FWhole<lower_temp) {
      digitalWrite(heater, HIGH);
    }
}

void printTemp(void) {
  Serial.println("temp is");
  Serial.println(Tc_100);
  compOn=digitalRead(compressor)==HIGH;
  heatOn=digitalRead(heater)==HIGH;
  if (compOn)  {
    Serial.println("compressor on");
  }
  if (heatOn)  {
    Serial.println("heater on");
  }
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Bounds: ");
  lcd.print(lower_temp);
  lcd.print("-->");
  lcd.print(upper_temp);
  lcd.print("F");
  lcd.setCursor(0,1);   
  lcd.print("Now: ");  
  if (SignBit) {  
     lcd.print("-");
  }
  lcd.print(Tc_100/100);
  lcd.print("C/");
  lcd.print(FWhole);
  lcd.print("F");
  if(compOn){
    lcd.print(" Cmp");    
  }
  if(heatOn){
    lcd.print(" Htr");    
  }  
}

void writeEEPROM(void){
  buffer.putFloat(Tc_100);
}

void loop(void) {
  knob_raw=analogRead(0);
  target_temp=map(knob_raw, 0, 1023, 30, 100);
  lower_temp=target_temp-plus_or_minus;
  upper_temp=target_temp+plus_or_minus;
  getTemp();
  
  if (relCycCnt == 10){// only change relays every 10 secs
    relCycCnt = 1;
    doRelays();
  }
//  writeEEPROM();
  relCycCnt+=1;
  printTemp();
  delay(1000);
}
